/*
 * Sala.java
 *
 * Criado em 9 de Setembro de 2007, 20:25
 */

package codebreaker.cliente.sala;

import codebreaker.cliente.jogo.JogoListener;
import codebreaker.commom.Jogador;
import codebreaker.protocolo.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 *
 * @author rodrigo
 */
public class Sala implements Runnable {
    
    private Socket socket;
    private InputStream in;
    private OutputStream out;
    
    /* lista de jogadores */
    private java.util.Set jogadores;
    
    private SalaListener salaListener;
    private JogoListener jogoListener;
    
    /**
     * Cria uma nova instância de Sala
     */
    public Sala(InetAddress servidor, int porta, Jogador jogador) {
	
	/* lista vazia */
	jogadores = new java.util.HashSet();
	jogadores.add(jogador);
	
	try {
	    /* conecta-se ao servidor */
	    socket = new Socket();
	    socket.setReceiveBufferSize(8192*100);
	    socket.connect(new InetSocketAddress(servidor, porta));	   
	    
	    /* associa entrada e saida */
	    in = socket.getInputStream();
	    out = socket.getOutputStream();
	    
	} catch (IOException ex) {
	    ex.printStackTrace();
	}
	
	/* inicia thread */
	Thread threadSala = new Thread(this);
	threadSala.start();
    }
    
    public String getNome(byte id) {
	
	for (java.util.Iterator i = jogadores.iterator(); i.hasNext(); ) {
	    Jogador jogador = (Jogador)i.next();
	    
	    if (jogador.getId() == id) {
		return jogador.getNome();
	    }
	}
	return null;
    }
    
    public Jogador getJogador(String nome) {
	for (java.util.Iterator i = jogadores.iterator(); i.hasNext(); ) {
	    Jogador jogador= (Jogador)i.next();
	    
	    if (jogador.getNome().equals(nome)) {
		return jogador;
	    }
	}
	return null;
    }
    
    public void run() {
	try {
	    
	    while(socket.isConnected()) {
		
		/* Le pacote */
		Pacote pacote = Pacote.ler(in);
		
		System.out.println("Sala: " + pacote);
		
		/* trata */
		switch (pacote.getID()) {
		    case Conexao.ID:
			Jogador novo = new Jogador(((Conexao)pacote).getNome(), ((Conexao)pacote).getIdJogador());
			jogadores.add(novo);
			salaListener.conexao(novo);
			break;
		    case EstadoJogador.ID:
			
			/* Encontra jogador */
			Jogador jogador = null;
			for (java.util.Iterator i = jogadores.iterator(); i.hasNext(); ) {
			    Jogador j= (Jogador)i.next();
			    
			    if (j.getId() == ((EstadoJogador)pacote).getIdJogador()) {
				jogador = j;
				break;
			    }
			}
			
			if (jogador == null)
			    break;
			
			if (((EstadoJogador)pacote).getEstado() == EstadoJogador.DESCONECTADO) {
			    jogadores.remove(jogador);
			    salaListener.desconexao(jogador);
			} else {
			    jogador.setEstado(((EstadoJogador)pacote).getEstado());
			    salaListener.mudouEstado(jogador);
			}
			break;
		    case ChatPublicoToCliente.ID:
			salaListener.recebeuChat((ChatPublicoToCliente) pacote);
			break;
		    case Convite.ID:
			salaListener.recebeuConvite((Convite) pacote);
			break;
		    case RespostaConvite.ID:
			salaListener.recebeuRespostaConvite((RespostaConvite) pacote);
			break;
		    case Chute.ID:
			if (jogoListener != null)
			    jogoListener.recebeuChute(((Chute)pacote).getChute());
			break;
		    case ChatPrivado.ID:
			if (jogoListener != null)
			    jogoListener.recebeuChat(((ChatPrivado)pacote).getTexto());
			break;
		    case FimJogo.ID:
			if (jogoListener != null)
			    jogoListener.fimJogo(((FimJogo)pacote).getMotivo());
			break;
		    default:
			System.err.println("Sala: pacote recebido do servidor invalido.");
		}
	    }
	} catch (IOException ex) {
	    ex.printStackTrace();
	}
    }
    
    /**
     * Envia uma mensagem de chat para o servidor
     */
    public void enviarChatPublico(String mensagem) {
	while (mensagem.length() > 0) {
	    String pac = mensagem.substring(0, Math.min(mensagem.length(), Constantes.TAMANHO_TEXTO));
	    enviar(new ChatPublicoToServidor(pac));
	    
	    mensagem = mensagem.substring(Math.min(mensagem.length(), Constantes.TAMANHO_TEXTO));
	}
    }
    
    /**
     * Envia uma mensagem de chat para o servidor
     */
    public void enviarChatPrivado(String mensagem) {
	while (mensagem.length() > 0) {
	    String pac = mensagem.substring(0, Math.min(mensagem.length(), Constantes.TAMANHO_TEXTO));
	    enviar(new ChatPrivado(pac));
	    
	    mensagem = mensagem.substring(Math.min(mensagem.length(), Constantes.TAMANHO_TEXTO));
	}
    }
    
    /**
     * Envia um pacote para o servidor
     */
    public synchronized void enviar(Pacote pacote) {
	try {
	    out.write(pacote.toBytes(true));
	    out.flush();
	} catch (IOException ex) {
	    ex.printStackTrace();
	}
    }
    
    public void close() {
	try {
	    in.close();
	    out.close();
	    socket.close();
	} catch (IOException ex) {
	    ex.printStackTrace();
	}
    }
    
    public java.util.Set getJogadores() {
	return jogadores;
    }
    
    public SalaListener getSalaListener() {
	return salaListener;
    }
    
    public void setSalaListener(SalaListener salaListener) {
	this.salaListener = salaListener;
    }
    
    public void setJogoListener(JogoListener jogoListener) {
	this.jogoListener = jogoListener;
    }
    
}
